Intro
In the backtesting analysis, I have established several different profitable strategies for timing entry/exits. Visit the XMR page to see how these signals were identified.
Simple moving average (SMA)
Exponential moving average (EMA)
SMA crosses
EMA crosses
Directional movement index (DMI)
True strength index (TSI) BEST
Stochastic oscillator (stoch)
Double RSI
Donchian channel
Know sure thing (KST)
Ensembl indicator
This script will examine the price action and these trade signals just before the daily close. If the signal is TRUE, it is bullish and if FALSE it is bearish. When there is a switch from bearish to bullish it is a buy signal and when it switches from bullish to bearish it is a sell signal. This HTML is updated just before the daily close each day, but push notifications for any trade signals are also sent by push bullet.
To receive these signals in real-time, subscribe to the following channels - it’s free for a limited time!
https://www.pushbullet.com/channel?tag=xmr_signal
If you need some help to design your own trading signals/strategies, I am happy to help for a fee. email me at mark.ziemann{αt}gmail.com for any enquiries/suggestions/feedback.
This report is distributed for FREE under the MIT licence, but if you find it useful, consider a small tip.
Reminder: this analysis is not financial advice.
suppressPackageStartupMessages({
library("jsonlite")
library("tidyverse")
library("runner")
library("quantmod")
library("TTR")
library("RPushbullet")
library("kableExtra")
})
TESTING = FALSE
MYNOTE = NULL
mydate <- Sys.time()
attr(mydate, "tzone") <- "UTC"
mydate <- as.Date(mydate)
Get XMR parameters
params <- read.table("https://mdz-analytics.com/coins/XMR/XMR_dat.txt", header=TRUE)
params %>% kbl(caption="optimised backtested parameters") %>% kable_styling("hover", full_width = F)
| indicator | parameter | meanROI | totalROI | ntrades | ndays | xhodl |
|---|---|---|---|---|---|---|
| SMA | 26 | 1.081940 | 89.80789 | 136 | 3050 | 0.9986643 |
| EMA | 19 | 1.063057 | 116.41114 | 177 | 3050 | 1.2944926 |
| SMAcross | 188,118 | 40.788815 | 2193.13683 | 7 | 3050 | 24.3876959 |
| EMAcross | 74,7 | 1.591188 | 747.85506 | 25 | 3050 | 8.3161532 |
| DMI | 66 | 2.049948 | 700.15611 | 23 | 3050 | 7.7857406 |
| DC | 28 | 1.408096 | 453.01425 | 28 | 3050 | 5.0375215 |
| TSI | 81,23,4 | 1.160863 | 1129.21810 | 87 | 3050 | 12.5569127 |
| stoch | 17,60,6 | 1.196081 | 995.63657 | 74 | 3050 | 11.0714852 |
| RSI2 | 32,89 | 1.093143 | 469.80768 | 143 | 3050 | 5.2242645 |
| KST | 1.2,0.18,49 | 1.214472 | 3246.12909 | 74 | 3050 | 36.0969767 |
| Ensemble | EMAcross,TSI,stoch,RSI2,DC,KST,3 | 1.173126 | 2206.94324 | 86 | 3050 | 40.7347497 |
Get XMR price data
Obtaining XMR price data (daily) for the last 300 days and today’s price.
URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=XMR&convert=USD&interval=daily&count=300"
download.file(URL,destfile="xmrdat.txt")
xmrdat <- fromJSON("xmrdat.txt")
price <- xmrdat$data$quotes
price <- data.frame( as.Date(price$time_close) , price$quote$USD$high, price$quote$USD$low, price$quote$USD$close)
colnames(price) <- c("date","high","low","close")
URL="https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?symbol=XMR&convert=USD&interval=hourly&time_period=hourly&count=11"
download.file(URL,destfile="xmrdat.txt")
xmrdat <- fromJSON("xmrdat.txt")
price2 <- xmrdat$data$quotes
price2 <- data.frame( as.Date(price2$time_close) , price2$quote$USD$high, price2$quote$USD$low, price2$quote$USD$close,stringsAsFactors=FALSE)
colnames(price2) <- c("date","high","low","close")
high <- max(price2[,2])
low <- min(price2[,3])
close <- price2[nrow(price2),4]
df <- data.frame(date=mydate,high=high,low=low,close=close,stringsAsFactors=FALSE)
price <- rbind(price,df)
tail(price) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close |
|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 |
if ( TESTING == TRUE) {
price[nrow(price),"Close"] <- price[nrow(price),"Close"] * 2
}
XMR SMA indicator
Now to determine whether XMR has crossed the SMA line.
price2 <- price
n <- as.numeric(params[params$indicator == "SMA",2])
price2$ma <- SMA(Cl(price2),n=n)
price2$signal <- price2$close > price2$ma
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | ma | signal |
|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 149.3779 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 149.0860 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 148.9583 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 148.6020 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 148.3655 | FALSE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 148.1050 | FALSE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_SMA=TRUE
} else {
ens_SMA=FALSE
}
message(paste("XMR SMA signal:",xmr_signal))
## XMR SMA signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
xlab="Date",ylab="price (USD)",main="XMR w SMA")
grid()
lines(price2$ma~ as.Date(price2$date) ,col="red")
if ( xmr_signal != "NONE") {
MYNOTE <- paste("The XMR SMA signal is", xmr_signal,".")
}
XMR EMA indicator
Now to determine whether XMR has crossed the EMA line.
price2 <- price
n <- as.numeric(params[params$indicator == "EMA",2])
price2$ma <- EMA(Cl(price2),n=n)
price2$signal <- price2$close > price2$ma
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | ma | signal |
|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 146.3076 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 145.7873 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 145.7795 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 145.6629 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 145.8262 | TRUE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 146.0011 | TRUE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_EMA=TRUE
} else {
ens_EMA=FALSE
}
message(paste("XMR EMA signal:",xmr_signal))
## XMR EMA signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
xlab="Date",ylab="price (USD)",main="XMR EMA")
grid()
lines(price2$ma~ as.Date(price2$date) ,col="red")
if ( xmr_signal != "NONE") {
MYNOTE <- paste("The XMR EMA signal is", xmr_signal,".")
}
XMR SMA cross indicator
The SMA cross is a reasonably good strategy.
price2 <- price
n <- as.numeric(unlist(strsplit(params[params$indicator == "SMAcross",2],",")))
n1 <- n[1]
n2 <- n[2]
price2$ma1 <- SMA(Cl(price2),n=n1)
price2$ma2 <- SMA(Cl(price2),n=n2)
price2$signal <- price2$ma2 > price2$ma1
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | ma1 | ma2 | signal |
|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 171.0662 | 148.3105 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 170.7963 | 147.7758 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 170.5402 | 147.3280 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 170.2595 | 146.8703 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 169.9583 | 146.4119 | FALSE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 169.6805 | 146.0186 | FALSE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_SMAcross=TRUE
} else {
ens_SMAcross=FALSE
}
message(paste("XMR SMA cross signal:",xmr_signal))
## XMR SMA cross signal: NONE
plot(price2$close~as.Date(price2$date),type="l",
xlab="Date",ylab="price (USD)",main="XMR w SMA cross")
grid()
lines(price2$ma1~ as.Date(price2$date) ,col="red")
lines(price2$ma2~ as.Date(price2$date) ,col="blue")
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE, "The XMR SMA cross signal is", xmr_signal,".")
}
XMR EMA cross indicator
The EMA cross is a moderately profitable strategy.
price2 <- price
n <- as.numeric(unlist(strsplit(params[params$indicator == "EMAcross",2],",")))
n1 <- n[1]
n2 <- n[2]
price2$ma1 <- EMA(Cl(price2),n=n1)
price2$ma2 <- EMA(Cl(price2),n=n2)
price2$signal <- price2$ma2 > price2$ma1
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | ma1 | ma2 | signal |
|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 151.4089 | 142.4285 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 151.1341 | 142.0974 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 150.9894 | 143.0004 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 150.8194 | 143.4035 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 150.7254 | 144.3767 | FALSE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 150.6414 | 145.1763 | FALSE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_EMAcross=TRUE
} else {
ens_EMAcross=FALSE
}
message(paste("XMR EMA cross signal is",xmr_signal))
## XMR EMA cross signal is NONE
plot(price2$close~as.Date(price2$date),type="l",
xlab="Date",ylab="price (USD)",main="XMR EMA cross")
grid()
lines(price2$ma1~ as.Date(price2$date) ,col="red")
lines(price2$ma2~ as.Date(price2$date) ,col="blue")
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE, "The XMR EMA cross signal is", xmr_signal,".")
}
XMR DMI indicator
Directional movement indicator is a good approach to identify trend changes.
n <- as.numeric(params[params$indicator == "DMI",2])
dmi.adx <- ADX(price[,c("high","low","close")],n=n)
price2 <- cbind(price,dmi.adx)
price2$signal <- dmi.adx[,1] > dmi.adx[,2]
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | DIp | DIn | DX | ADX | signal |
|---|---|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 17.66315 | 22.33587 | 11.682092 | 8.326711 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 17.63814 | 22.17759 | 11.401161 | 8.373294 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 17.71896 | 21.95651 | 10.680525 | 8.408252 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 18.54223 | 21.60998 | 7.640315 | 8.396616 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 18.31140 | 21.80999 | 8.720005 | 8.401516 | FALSE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 18.43643 | 21.72227 | 8.182149 | 8.398192 | FALSE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_DMI=TRUE
} else {
ens_DMI=FALSE
}
message(paste("XMR DMI signal:",xmr_signal))
## XMR DMI signal: NONE
price2 <- as.data.frame(price2)
par(mfrow=c(2,1))
plot(price2$close~as.Date(price2$date),type="l",
xlab="Date",ylab="price (USD)",main="XMR USD price")
grid()
plot(price2$DIp~as.Date(price2$date),type="l", col="blue",
xlab="Date",ylab="price (USD)",main="XMR DMI")
grid()
lines(price2$DIn ~ as.Date(price2$date) ,col="red")
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE,"XMR DMI signal is", xmr_signal,".")
}
XMR TSI indicator
True Strength Indicator is one of the more profitable approaches. Its success lies in how it changes rapidly when momentum shifts. For most coins, this indicator performs “best” in backtesting analysis, which means it should carry relatively more weight than other indicators.
n <- as.numeric(unlist(strsplit(params[params$indicator == "TSI",2],",")))
n1 <- n[1]
n2 <- n[2]
ns <- n[3]
TSI <- function(x, n.first = 25, n.second = 13, n.signal = 7) {
#True Strength Indicator
#https://school.stockcharts.com/doku.php?id=technical_indicators:true_strength_index
x <- try.xts(x, error = as.matrix)
pc <- x - lag.xts(x, na.pad = T) #force lag.xts to get na padding
dspc <- EMA(EMA(pc, n = n.first), n = n.second)
dsapc <- EMA(EMA(abs(pc), n = n.first), n = n.second)
tsi <- 100 * (dspc/dsapc)
signal <- EMA(tsi, n = n.signal)
r <- cbind(tsi, signal)
r <- reclass(r, x)
if (!is.null(dim(r))) colnames(r) <- c("tsi", "signal")
return(r)
}
tsi <- TSI(price$close , n.first = n1, n.second = n2, n.signal = ns )
colnames(tsi) <- c("tsi","sig")
price2 <- cbind(price,tsi)
price2$signal <- tsi[,1] > tsi[,2]
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | tsi | sig | signal |
|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | -3.392380 | -3.052215 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | -3.579238 | -3.263025 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | -3.546762 | -3.376520 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | -3.562248 | -3.450811 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | -3.457844 | -3.453624 | FALSE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | -3.350880 | -3.412526 | TRUE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_TSI=TRUE
} else {
ens_TSI=FALSE
}
message(paste("XMR TSI signal:",xmr_signal))
## XMR TSI signal: BUY
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
xlab="Date",ylab="price (USD)",main="USD price")
grid()
plot(tsi[,1] ~ as.Date(price2$date),type="l",col="blue",
xlab="Date",ylab="TSI",main="TSI")
lines(as.Date(price2$date), tsi[,2] , col="red" )
grid()
par(mfrow=c(1,1))
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE,"XMR TSI signal is", xmr_signal,".")
}
XMR stochastic oscillator indicator
Similar to the TSI, the stoch can pinpoint early changes in momentum, however it may give many false positives.
n <- as.numeric(unlist(strsplit(params[params$indicator == "stoch",2],",")))
n1 <- n[1]
n2 <- n[2]
n3 <- n[3]
sto <- stoch(HLC(price), nFastK=n1 , nFastD=n2 , nSlowD=n2 , bounded = TRUE, smooth=n3)
price2 <- cbind(price,sto)
price2$signal <- price2$fastK > price2$fastD
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | fastK | fastD | slowD | signal |
|---|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 0.2047479 | 0.5318638 | 0.6157778 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 0.2143011 | 0.5207693 | 0.6153552 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 0.2384226 | 0.5099432 | 0.6147129 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 0.2894465 | 0.4998074 | 0.6138688 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 0.3061969 | 0.4904259 | 0.6128416 | FALSE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 0.3392374 | 0.4817052 | 0.6116438 | FALSE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_stoch=TRUE
} else {
ens_stoch=FALSE
}
message(paste("XMR stoch signal:",xmr_signal))
## XMR stoch signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
xlab="Date",ylab="price (USD)",main="USD price")
grid()
plot(price2$fastK ~ as.Date(price2$date),type="l",col="blue",
xlab="Date",ylab="index",main="stochastic oscillator")
lines(as.Date(price2$date), price2$fastD , col="red" )
grid()
par(mfrow=c(1,1))
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE,"XMR Stoch signal is", xmr_signal,".")
}
XMR double RSI indicator
Double RSI is simply two RSI lines.
n <- as.numeric(unlist(strsplit(params[params$indicator == "RSI2",2],",")))
n1 <- n[1]
n2 <- n[2]
rsi1 <- RSI(price$close,n=n1,maType=EMA)
rsi2 <- RSI(price$close,n=n2,maType=EMA)
price2 <- cbind(price,rsi1,rsi2)
price2$signal <- price2$rsi1 > price2$rsi2
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | rsi1 | rsi2 | signal |
|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 44.97797 | 47.38342 | FALSE |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 44.53856 | 47.23518 | FALSE |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 48.28575 | 48.38581 | FALSE |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 47.47291 | 48.13027 | FALSE |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 49.67966 | 48.80695 | TRUE |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 49.91279 | 48.87794 | TRUE |
today_signal <- price2[nrow(price2),"signal"]
previous_signal <- price2[(nrow(price2)-1),"signal"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
xmr_signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
xmr_signal="SELL"
}
} else {
xmr_signal <- "NONE"
}
if (today_signal==TRUE) {
ens_RSI2=TRUE
} else {
ens_RSI2=FALSE
}
message(paste("XMR RSI signal:",xmr_signal))
## XMR RSI signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
xlab="Date",ylab="price (USD)",main="USD price")
grid()
plot(price2$rsi1 ~ as.Date(price2$date),type="l",col="blue",
xlab="Date",ylab="index",main="double RSI")
lines(as.Date(price2$date), price2$rsi2 , col="red" )
grid()
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
xlab="Date",ylab="price (USD)",main="USD price")
grid()
plot(price2$rsi1/price2$rsi2 ~ as.Date(price2$date),type="l",
xlab="Date",ylab="RSI ratio",main="double RSI")
grid()
abline(h=1,lty=2,lwd=2)
par(mfrow=c(1,1))
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE,"XMR RSI2 signal is", xmr_signal,".")
}
XMR Donchian channel indicator
n <- as.numeric(params[params$indicator == "DC",2])
price2 <- price[1:nrow(price)-1,]
dc <- DonchianChannel(price2$close,n=n)
price2$higher <- c(NA,sapply(2:nrow(dc),function(i) {
dc[i,"high"] > dc[(i-1),"high"]
} ))
price2$lower <- c(NA,sapply(2:nrow(dc),function(i) {
dc[i,"low"] < dc[(i-1),"low"]
} ))
price2 <- price2[price2$higher != price2$lower,]
# show changing rows only
price2 <- price2[c(NA,unlist(lapply(2:nrow(price2) , function(i) {
price2$higher[i] != price2$higher[i-1]
}))),]
price2 <- price2[!is.na(price2$higher),]
previous_signal <- price2[nrow(price2),"higher"]
price2 <- price
dc <- DonchianChannel(price2$close,n=n)
colnames(dc) <- c("dchigh","dcmid","dclow")
price2 <- cbind(price2,dc)
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | dchigh | dcmid | dclow |
|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | 163.9119 | 149.7593 | 135.6067 |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | 163.9119 | 149.7593 | 135.6067 |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | 163.9119 | 149.7593 | 135.6067 |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | 163.9119 | 149.7593 | 135.6067 |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | 163.9119 | 149.7593 | 135.6067 |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | 163.9119 | 149.7593 | 135.6067 |
xmr_signal="NONE"
# if we in negative territory, check whether time to buy
if ( previous_signal == FALSE ) {
if ( price2[nrow(price2),"dchigh"] > price2[nrow(price2)-1,"dchigh"] ) {
xmr_signal="BUY"
}
}
# if we in positive territory, check whether time to sell
if ( previous_signal == TRUE ) {
if ( price2[nrow(price2),"dclow"] < price2[nrow(price2)-1,"dclow"] ) {
xmr_signal="SELL"
}
}
if ( xmr_signal=="NONE" ) {
today_signal=previous_signal
} else {
if (xmr_signal=="BUY") { today_signal = TRUE }
if (xmr_signal=="SELL") { today_signal = FALSE }
}
if (today_signal==TRUE) {
ens_DC=TRUE
} else {
ens_DC=FALSE
}
message(paste("XMR DC signal:",xmr_signal))
## XMR DC signal: NONE
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
xlab="Date",ylab="price (USD)",main="USD price",lwd=2)
grid()
lines(price2$dclow~ as.Date(price2$date),lwd=1.5,col="red")
lines(price2$dchigh~ as.Date(price2$date),lwd=1.5,col="limegreen")
price2 <- tail(price2,100)
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
xlab="Date",ylab="price (USD)",main="USD price",lwd=2)
grid()
lines(price2$dclow~ as.Date(price2$date),lwd=1.5,col="red")
lines(price2$dcmid~ as.Date(price2$date),lwd=1.5,col="gray")
lines(price2$dchigh~ as.Date(price2$date),lwd=1.5,col="limegreen")
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE,"XMR Donchian channel signal is", xmr_signal,".")
}
XMR KST indicator
Another high-performing indicator across different price series data.
price2 <- price
n <- as.numeric(unlist(strsplit(params[params$indicator == "KST",2],",")))
nScale <- n[1]
nrocScale <- n[2]
nSigs <- n[3]
kst <- KST(price2$close,n=nScale * c(10, 10, 10, 15) ,
nROC=nrocScale * c(10, 15, 20, 30),
nSig=nSigs)
price2 <- cbind(price2,kst)
price2$KST <- as.numeric(kst[,1]>kst[,2])
tail(price2) %>% kbl(row.names = FALSE) %>% kable_styling("hover", full_width = F)
| date | high | low | close | kst | signal | KST |
|---|---|---|---|---|---|---|
| 2022-09-24 | 143.9085 | 140.7304 | 141.7651 | -23.477129 | -3.511337 | 0 |
| 2022-09-25 | 144.5276 | 140.1472 | 141.1041 | -19.273361 | -4.365961 | 0 |
| 2022-09-26 | 146.1058 | 139.9758 | 145.7094 | -13.152069 | -5.037067 | 0 |
| 2022-09-27 | 152.8920 | 143.1812 | 144.6130 | -9.681649 | -5.472140 | 0 |
| 2022-09-28 | 147.9419 | 140.3032 | 147.2961 | -8.171095 | -5.892443 | 0 |
| 2022-09-29 | 149.1473 | 146.7070 | 147.5753 | -8.423658 | -6.314720 | 0 |
today_signal <- price2[nrow(price2),"KST"]
previous_signal <- price2[(nrow(price2)-1),"KST"]
if (today_signal != previous_signal ) {
if ( (today_signal == TRUE ) & (previous_signal == FALSE ) ) {
signal="BUY"
}
if ( (today_signal == FALSE ) & (previous_signal == TRUE ) ) {
signal="SELL"
}
} else {
signal <- "NONE"
}
if (today_signal==TRUE) {
ens_DMI=TRUE
} else {
ens_DMI=FALSE
}
message(paste("XMR KST signal:",xmr_signal))
## XMR KST signal: NONE
par(mfrow=c(2,1))
plot(price2$close ~ as.Date(price2$date),type="l",log="y",
xlab="Date",ylab="price (USD)",main="USD price")
grid()
plot(kst[,1] ~ as.Date(price2$date),type="l",col="blue",
xlab="Date",ylab="KST",main="KST")
lines(as.Date(price2$date), kst[,2] , col="red" )
grid()
par(mfrow=c(1,1))
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE,"XMR KST signal is", xmr_signal,".")
}
XMR Ensemble indicator
This is a combination of a number of indicators.
ens <- params[params$indicator=="Ensemble","parameter"]
myrev <- intToUtf8(rev(utf8ToInt(ens)))
myrev <- unlist(strsplit(myrev,","))
# get thresh
n <- as.numeric(myrev[1])
myrev <- myrev[2:length(myrev)]
# get combination
combo <- sapply(myrev,function(s) { intToUtf8(rev(utf8ToInt(s))) })
message(paste("The combination is",paste(combo,collapse=" ")))
## The combination is KST DC RSI2 stoch TSI EMAcross
message(paste("The buy threshold is",n))
## The buy threshold is 3
indicators <- c("SMA"=ens_SMA,
"EMA"=ens_EMA,
"SMAcross"=ens_SMAcross,
"EMAcross"=ens_EMAcross,
"DMI"=ens_DMI,
"TSI"=ens_TSI,
"stoch"=ens_stoch,
"RSI2"=ens_RSI2,
"DC"=ens_DC)
indicators <- indicators[names(indicators) %in% combo]
message("State of the indicators:")
## State of the indicators:
indicators
## EMAcross TSI stoch RSI2 DC
## FALSE TRUE FALSE TRUE FALSE
today_count <- sum(indicators)
message(paste("today_count_XMR",today_count,sep="="))
## today_count_XMR=2
today_signal <- today_count>=n
prev_html <- readLines("https://mdz-analytics.com/coins/XMR/alerts_XMR.html")
prev_signal <- length(grep("XMR ensemble indicator is BULLISH",prev_html))>2
xmr_signal <- "NONE"
if ( today_signal != prev_signal ) {
if ( today_signal == TRUE ) {
xmr_signal="BUY"
} else {
xmr_signal="SELL"
}
}
if (today_signal==TRUE) {
message("XMR ensemble indicator is BULLISH")
} else {
message("XMR ensemble indicator is BEARISH")
}
## XMR ensemble indicator is BEARISH
message(paste("XMR ENS signal:",xmr_signal))
## XMR ENS signal: NONE
if ( xmr_signal != "NONE") {
MYNOTE <- paste(MYNOTE,"XMR Ensemble indicator is", xmr_signal,".")
}
Send a push notification.
MYNOTE
## [1] " XMR TSI signal is BUY ."
if ( !is.null(MYNOTE) ) {
MYNOTE <- paste(MYNOTE, ". Visit https://mdz-analytics.com/coins/XMR/alerts_XMR.html for the details")
MYNOTE
pbPost("note", "Crypto Alert", MYNOTE ,channel="xmr_signal")
}
Session information
For reproducibility
Click HERE to show session info
sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: aarch64-unknown-linux-gnu (64-bit)
## Running under: Ubuntu 22.04.1 LTS
##
## Matrix products: default
## BLAS: /usr/lib/aarch64-linux-gnu/blas/libblas.so.3.10.0
## LAPACK: /usr/lib/aarch64-linux-gnu/lapack/liblapack.so.3.10.0
##
## locale:
## [1] LC_CTYPE=en_AU.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_AU.UTF-8 LC_COLLATE=en_AU.UTF-8
## [5] LC_MONETARY=en_AU.UTF-8 LC_MESSAGES=en_AU.UTF-8
## [7] LC_PAPER=en_AU.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_AU.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] kableExtra_1.3.4 RPushbullet_0.3.4 quantmod_0.4.20 TTR_0.24.3
## [5] xts_0.12.1 zoo_1.8-10 runner_0.4.1 forcats_0.5.1
## [9] stringr_1.4.0 dplyr_1.0.9 purrr_0.3.4 readr_2.1.2
## [13] tidyr_1.2.0 tibble_3.1.8 ggplot2_3.3.6 tidyverse_1.3.2
## [17] jsonlite_1.8.0
##
## loaded via a namespace (and not attached):
## [1] httr_1.4.4 sass_0.4.2 viridisLite_0.4.0
## [4] modelr_0.1.8 bslib_0.4.0 assertthat_0.2.1
## [7] highr_0.9 googlesheets4_1.0.1 cellranger_1.1.0
## [10] yaml_2.3.5 pillar_1.8.0 backports_1.4.1
## [13] lattice_0.20-45 glue_1.6.2 digest_0.6.29
## [16] rvest_1.0.2 colorspace_2.0-3 htmltools_0.5.3
## [19] pkgconfig_2.0.3 broom_1.0.0 haven_2.5.0
## [22] bookdown_0.28 scales_1.2.0 webshot_0.5.3
## [25] svglite_2.1.0 tzdb_0.3.0 googledrive_2.0.0
## [28] generics_0.1.3 ellipsis_0.3.2 cachem_1.0.6
## [31] withr_2.5.0 cli_3.3.0 magrittr_2.0.3
## [34] crayon_1.5.1 readxl_1.4.1 evaluate_0.16
## [37] fs_1.5.2 fansi_1.0.3 xml2_1.3.3
## [40] tools_4.1.2 hms_1.1.1 gargle_1.2.0
## [43] lifecycle_1.0.1 munsell_0.5.0 reprex_2.0.2
## [46] compiler_4.1.2 jquerylib_0.1.4 systemfonts_1.0.4
## [49] rlang_1.0.4 grid_4.1.2 rstudioapi_0.13
## [52] rmarkdown_2.15 gtable_0.3.0 DBI_1.1.3
## [55] curl_4.3.2 R6_2.5.1 lubridate_1.8.0
## [58] knitr_1.39 fastmap_1.1.0 utf8_1.2.2
## [61] stringi_1.7.8 parallel_4.1.2 rmdformats_1.0.4
## [64] Rcpp_1.0.9 vctrs_0.4.1 dbplyr_2.2.1
## [67] tidyselect_1.1.2 xfun_0.32